﻿using CommonDevelop;
using CommonDevelop.DB;
using CommonEngine;
using CommonEngine.Security;
using ManageDB;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace ManageRepository
{
    /// <summary>
    /// 用户主键接口
    /// </summary>
    public interface IUserRepository : IBase<Base_User>
    {
        /// <summary>
        /// 账户不能重复，验证账户是否已经存在
        /// </summary>
        bool ExistAccount(string account, string UserId);
        /// <summary>
        /// 过滤未存在的账号数据
        /// </summary>
        List<string> FilterAccount(List<string> Accounts);

        /// <summary>
        /// 通过账号找用户主键
        /// </summary>
        Base_User GetUserByAccount(string account);
        /// <summary>
        /// 修改密码
        /// </summary>
        bool RevisePassword(string password, string UserId, string LoginUserId, string LoginUserName);

        IEnumerable<Base_User> GetJobByCompanyId(string CompanyId);
        IEnumerable<Base_User> GetJobByDeptId(string DeptId);
        IEnumerable<Base_User> GetUserJobSets(Pagination Pag, string CompanyId, string DeptId, string keyword);

    }

    /// <summary>
    /// 用户主键
    /// </summary>
    public class UserRepository : DBBase<Base_User>, IUserRepository
    {
        #region--重构--

        /// <summary>
        /// 维护一个场景的应用输出，通过一个关键字，确认相关机构集合
        /// </summary>
        public override Expression<Func<Base_User, bool>> WhereKeyWord(string keyword)
           => t => t.Account.Contains(keyword) || t.JobNumber.Contains(keyword);

        /// <summary>
        /// 维护一个场景的应用输出，获取缓存的用户数据时，过滤调度敏感字段
        /// </summary>
        public override Base_User GetEntity(object keyValue)
        {
            var data = base.GetEntity(keyValue);
            if (data != null)
                data.Password = "";    //去掉关键信息

            return data;
        }

        public override IEnumerable<Base_User> GetList(string keyword = null, bool IsDelete = false)
        {
            var data = base.GetList(keyword, IsDelete);
            if (data.IsNotNullOrEmpty())
                data.ToList().ForEach(x => x.Password = "");

            return data;
        }

        public override IEnumerable<Base_User> GetList(Expression<Func<Base_User, bool>> expression, bool IsDelete = false)
        {
            var data = base.GetList(expression, IsDelete);
            if (data.IsNotNullOrEmpty())
                data.ToList().ForEach(x => x.Password = "");

            return data;
        }

        public override IEnumerable<Base_User> GetPageList(Pagination Pag, Expression<Func<Base_User, bool>> expression, bool IsDelete = false)
        {
            var data = base.GetPageList(Pag, expression, IsDelete);
            if (data.IsNotNullOrEmpty())
                data.ToList().ForEach(x => x.Password = "");

            return data;
        }

        public override IEnumerable<Base_User> GetPageList(Pagination Pag, string keyword = null, bool IsDelete = false)
        {
            var data = base.GetPageList(Pag, keyword, IsDelete);
            if (data.IsNotNullOrEmpty())
                data.ToList().ForEach(x => x.Password = "");

            return data;
        }

        /// <summary>
        /// 拉关系
        /// </summary>
        public override IEnumerable<TVO> GetPull<TVO>(Base_User en)
        {
            if (en == null || en.UserId.IsEmpty())
                return base.GetPull<TVO>(en);

            string UserId = en.UserId;
            if (typeof(TVO).Equals(typeof(Base_Position)))   //岗位
            {
                var db = SugarBizDB.GetReadOnlyInstance();
                //链表查询--用户关联的岗位
                List<Base_Position> result = db.Queryable<Base_User, Base_UserRelation, Base_Position>(
                    (uu, ur, post)
                    => new JoinQueryInfos(JoinType.Left, uu.UserId == ur.UserId,
                    JoinType.Left, ur.RelObjectId == post.PositionId && ur.RelType == 2))
                    .Where(uu => uu.UserId == UserId)
                    .OrderBy(uu => uu.LastModified, OrderByType.Desc)
                    .Select<Base_Position>((uu, ur, post) => post)
                    .ToList();

                return result.Cast<TVO>().ToList();
            }
            else if (typeof(TVO).Equals(typeof(Base_Dept)))   //部门
            {
                var db = SugarBizDB.GetReadOnlyInstance();
                //链表查询--用户关联的部门
                List<Base_Dept> result = db.Queryable<Base_User, Base_UserRelation, Base_Dept>(
                    (uu, ur, dd)
                    => new JoinQueryInfos(JoinType.Left, uu.UserId == ur.UserId,
                    JoinType.Left, ur.RelObjectId == dd.DeptId && ur.RelType == 1))
                    .Where(uu => uu.UserId == UserId)
                    .OrderBy(uu => uu.LastModified, OrderByType.Desc)
                    .Select<Base_Dept>((uu, ur, dd) => dd)
                    .ToList();

                return result.Cast<TVO>().ToList();
            }
            else
                return base.GetPull<TVO>(en);
        }

        #endregion

        #region--接口实现01--

        /// <summary>
        /// 账户不能重复，验证账户是否重复
        /// </summary>
        public bool ExistAccount(string account, string UserId)
        {
            var expression = LinqExtend.True<Base_User>();
            expression = expression.And(t => t.Account == account);

            if (!string.IsNullOrEmpty(UserId))
                expression = expression.And(t => t.UserId != UserId);

            return SugarBizDB.GetReadOnlyMore(expression).Count() == 0 ? false : true;
        }
        /// <summary>
        /// 过滤未存在的账号数据
        /// </summary>
        public List<string> FilterAccount(List<string> Accounts)
        {
            if (Accounts.IsNullOrEmpty())
                return new List<string>();

            var query = SugarBizDB.GetReadOnlyMore<Base_User>(a => a.IsDelete == false && Accounts.Contains(a.Account));
            List<string> ALs = query.Select(a => a.Account).ToList();
            return Accounts.Except(ALs).ToList();  //取差集--返回未进表的账号
        }

        /// <summary>
        /// 获取用户实体(根据用户账号)
        /// </summary>
        public Base_User GetUserByAccount(string account)
            => account.IsEmpty() ? null
            : SugarBizDB.GetReadOnlyOne<Base_User>(a => a.Account == account && a.IsDelete == false);

        /// <summary>
        /// 修改用户登录密码
        /// </summary>
        public bool RevisePassword(string password, string UserId, string LoginUserId, string LoginUserName)
        {
            //新密码（MD5 小写）
            if (UserId.IsEmpty() || password.IsEmpty())
                return false;

            Base_User userEntity = this.GetEntity(UserId);
            if (userEntity != null)
            {
                userEntity.Modified(DateTime.Now);
                userEntity.ModifyUserId = LoginUserId;
                userEntity.ModifyUserName = LoginUserName;
                userEntity.Secretkey = CommonOP.MakeSecretkey();
                userEntity.Password = Md5Helper.Encrypt(DESEncrypt.Encrypt(password, userEntity.Secretkey).ToLower(), 32).ToLower();
                //开事务更新
                return this.Update_Entity(userEntity, true);
            }
            else
                return false;
        }

        #endregion

        public IEnumerable<Base_User> GetJobByCompanyId(string CompanyId)
            => CompanyId.IsEmpty() ? new List<Base_User>() : this.GetList(a => a.CompanyId == CompanyId, false);

        public IEnumerable<Base_User> GetJobByDeptId(string DeptId)
            => DeptId.IsEmpty() ? new List<Base_User>() : this.GetList(a => a.DepartmentId == DeptId, false);

        public IEnumerable<Base_User> GetUserJobSets(Pagination Pag, string CompanyId, string DeptId, string keyword)
        {
            var expression = LinqExtend.True<Base_User>();
            if (!CompanyId.IsEmpty())
                expression = expression.And(t => t.CompanyId == CompanyId);
            if (!DeptId.IsEmpty())
                expression = expression.And(t => t.DepartmentId == DeptId);
            if (!keyword.IsEmpty())
                expression = expression.And(this.WhereKeyWord(keyword));

            return this.GetPageList(Pag, expression, false);
        }
    }
}
